home *** CD-ROM | disk | FTP | other *** search
- /*
- * Usage:
- * domap [file1] [file2] [file3] [...] [options] | pen xcenter=0 ycenter=0
- * ^^^
- * A Vplot filter
- *
- * If project=round, this program projects the Earth onto a plane tangent
- * to its surface, as seen from your "eye", where the position of your eye
- * is given by the following parameters:
- *
- * If project=round
- * lat=37.45 <- Latitude of eye
- * long=-122.21 <- Longitude of eye
- * dist=100. <- Distance of eye above Earth, in miles
- * inch=110. <- Miles per inch at center of projection
- *
- * If project=flat, a crude latitude-longitude plot is made instead.
- *
- * If project=flat
- * long=-122.21 <- Longitude centered in the plot
- *
- * file1, file2, file3, etc, are map information files
- * such as are in ./Namer.Map/*.cbd, etc.
- *
- * A slew of other options are used to control what sorts of objects
- * get plotted, and in what colors. These are:
- *
- * pby1=6 <- Vplot color to make this type of object; 0 means omit
- * pby2=6
- * pby3=5
- *
- * bdy1=7
- * bdy2=7
- * bdy3=6
- *
- * riv1=5
- * riv2=1
- * riv3=1
- * riv4=1
- * riv5=5
- * riv6=1
- * riv7=1
- * riv8=1
- * riv9=1
- * riv10=1
- * riv11=1
- * riv12=1
- *
- * cil1=7
- * cil2=4
- * cil3=1
- * cil4=1
- * cil5=1
- * cil6=1
- * cil7=1
- * cil8=1
- * cil9=1
- * cil10=1
- * cil11=1
- * cil12=1
- * cil13=1
- * cil14=1
- * cil15=1
- *
- * The meanings of these different objects are defined in the
- * "Database_info" file.
- *
- * To read the data files properly, you may need to rewrite the
- * "twiddle32" and "twiddle16" subroutines. The data files are
- * integers, and so preoper reading of them depends on the byte
- * ordering of your machine.
- *
- */
- #include <stdio.h>
- #include <math.h>
- #include <vplot.h>
- #include <strings.h>
-
- /*
- * Much of this program was written by Brian Reid at the Dec
- * Western Research Lab. The rest was written by Joe Dellinger
- * at Stanford University. Neither of us much cares what becomes
- * of it. Sat Apr 1 01:26:51 PST 1989
- */
-
- /* ----------------------------------------------------------------------
- * Read and process one binary map file.
- */
-
- #include <sys/file.h>
-
- #define SHORTFLAG 0x4000
- #define CBD_MAGIC 0x20770002
- #define BIT32 int
- #define BIT16 short
-
- #define CONV (3.141592654 / 180.)
-
- /*
- * Input parameters:
- * viewlat, viewlong = lat, long in center of picture;
- * viewdist = distance of eye from earth, in miles;
- * viewscale = miles per inch at center of picture
- *
- * For project=round, all of these are ignored except
- * viewlong.
- */
- double viewlat, viewlong, viewdist, viewscale;
- char projection[80];
-
- /*
- * for getpar
- */
- int xargc;
- char **xargv;
-
- struct cbdhead
- {
- BIT32 magic; /* Magic number */
- BIT32 dictaddr; /* Offset of segment dictionary in file */
- BIT32 segcount; /* Number of segments in file */
- BIT32 segsize; /* Size of segment dictionary */
- BIT32 segmax; /* Size of largest segment's strokes, /2 */
- BIT32 fill[(40 / sizeof (BIT32)) - 5]; /* Filler */
- };
-
- main (argc, argv)
- int argc;
- char **argv;
- {
- int Ifile, segcount, idx, idy, segbufsize, olt, oln, j, k, jstroke, iseg;
- int colfile[20];
- char string[80], string2[80], *sptr;
- char filename[20][80];
- int filenum;
- BIT32 i32;
- BIT16 *segbuf;
- double x, y, z, x1, x2, xc, y1, y2, yc, z1, z2, zc;
- double dist, cent, clipdist, horizon, my_acos ();
- double longi, lati;
-
- struct segdict
- {
- BIT32 segid;
- BIT32 maxlat, minlat, maxlong, minlong;
- BIT32 absaddr;
- BIT16 nbytes;
- BIT16 rank;
- } *sd, *sdbuf;
-
- struct segment
- {
- BIT32 orgx, orgy;
- BIT32 id;
- BIT16 nstrokes;
- BIT16 dummy;
- } sb;
-
- struct cbdhead header;
-
- #ifdef DEBUG
- int deg, min, sec, count;
- #endif
-
-
- xargc = argc;
- xargv = argv;
-
- vp_filep (stdout);
-
- viewlat = 40.;
- viewlong = -90.;
- viewdist = 100000.;
- viewscale = 100.;
-
- getpar ("lat", "g", &viewlat);
- getpar ("long", "g", &viewlong);
- getpar ("dist", "g", &viewdist);
- getpar ("inch", "g", &viewscale);
-
- viewlat *= CONV;
- viewlong *= CONV;
- viewdist /= 3950.;
- viewscale /= 3950.;
-
- strcpy (projection, "round");
- getpar ("project", "s", projection);
-
- if (projection[0] == 'r')
- vp_scale (1. / viewscale, 1. / viewscale);
- else
- vp_scale (5. / (180. * CONV), 5. / (180. * CONV));
-
- clipdist = my_acos (1. / (1. + viewdist));
-
- vp_color (WHITE);
- vp_penup ();
- vp_fat (1);
-
- if (projection[0] == 'r')
- {
- horizon = tan (clipdist / 2.);
- for (j = 0; j <= 360 * 10; j++)
- {
- vp_upendn (horizon * cos (j * CONV / 10.), horizon * sin (j * CONV / 10.));
- }
- }
- else
- {
- vp_move (-5., -2.5);
- vp_draw (5., -2.5);
- vp_draw (5., 2.5);
- vp_draw (-5., 2.5);
- vp_draw (-5., -2.5);
- }
-
- for (j = 0; j < 20; j++)
- {
- strcpy (filename[j], "");
- }
-
- for (filenum = 1; filenum < argc; filenum++)
- {
-
- strcpy (filename[filenum], argv[filenum]);
-
- if (filename[filenum][0] == '\0'
- ||
- index (filename[filenum], '=') != NULL
- )
- continue;
-
- Ifile = open (filename[filenum], O_RDONLY, 0);
-
- if (Ifile == -1)
- continue;
-
- for (j = 0; j < 20; j++)
- {
- colfile[j] = 0;
- }
-
- sptr = rindex (filename[filenum], '.');
- if (sptr == NULL)
- continue;
- if (strcmp (sptr, ".cbd") != 0)
- continue;
-
- strcpy (string2, sptr - 3);
- string2[3] = '\0';
-
- colfile[1] = WHITE;
- colfile[2] = CYAN;
-
- for (j = 0; j < 20; j++)
- {
- sprintf (string, "%s%d", string2, j);
- getpar (string, "d", &colfile[j]);
- }
-
- /*
- * Read in the file header, check it for the correct magic number,
- * and learn the address of the segment dictionary
- */
- read (Ifile, &header, sizeof header);
-
- twiddle32 (&(header.magic));
- twiddle32 (&(header.dictaddr));
- twiddle32 (&(header.segcount));
- twiddle32 (&(header.segsize));
- twiddle32 (&(header.segmax));
-
- if (header.magic != CBD_MAGIC)
- {
- fprintf (stderr, "File has bad magic number %d != %d\n",
- header.magic, CBD_MAGIC);
- exit (2);
- }
-
- /* allocate space for the segment buffer */
- segbufsize = 2 * header.segmax;
- segbuf = (BIT16 *) malloc (50 + segbufsize);
-
- /* allocate space for the segment dictionary */
- sdbuf = (struct segdict *) malloc (100 + header.segsize);
- sd = sdbuf;
- sd++;
-
- /* Go read in the segment dictionary (it's at the end of the file) */
- lseek (Ifile, header.dictaddr, L_SET);
- j = read (Ifile, sd, header.segsize);
-
- if (j < header.segsize)
- {
- fprintf (stderr, "File segment dictionary expecting %d got %d\n",
- header.segsize, j);
- close (Ifile);
- free (sdbuf);
- free (segbuf);
- return;
- }
-
- /*
- * Now look at each segment and decide if we're
- * going to keep it or not
- */
- segcount = header.segcount;
-
- sd = sdbuf;
- for (iseg = 1; iseg <= segcount; iseg++)
- {
- sd++; /* does this really work? wow! */
-
- twiddle32 (&(sd->segid));
- twiddle32 (&(sd->maxlat));
- twiddle32 (&(sd->minlat));
- twiddle32 (&(sd->maxlong));
- twiddle32 (&(sd->minlong));
- twiddle32 (&(sd->absaddr));
- twiddle16 (&(sd->nbytes));
- twiddle16 (&(sd->rank));
-
- if (colfile[sd->rank] == 0)
- continue;
-
- if (projection[0] == 'r')
- {
- longi = sd->maxlong * CONV / 3600.;
- lati = sd->maxlat * CONV / 3600;
-
- x = sin (longi - viewlong) * cos (lati);
- y = cos (longi - viewlong) * cos (lati);
- z = sin (lati);
-
- y1 = y * cos (viewlat) + z * sin (viewlat);
- z1 = -y * sin (viewlat) + z * cos (viewlat);
- x1 = x;
-
- longi = sd->minlong * CONV / 3600;
- lati = sd->minlat * CONV / 3600;
- x = sin (longi - viewlong) * cos (lati);
- y = cos (longi - viewlong) * cos (lati);
- z = sin (lati);
-
- y2 = y * cos (viewlat) + z * sin (viewlat);
- z2 = -y * sin (viewlat) + z * cos (viewlat);
- x2 = x;
-
- xc = (x1 + x2) / 2.;
- yc = (y1 + y2) / 2.;
- zc = (z1 + z2) / 2.;
- x = sqrt (xc * xc + yc * yc + zc * zc);
- xc /= x;
- yc /= x;
- zc /= x;
-
- dist = my_acos (xc * x1 + yc * y1 + zc * z1);
- cent = my_acos (yc);
-
- if (cent - dist > clipdist)
- continue;
- }
-
- vp_color (colfile[sd->rank]);
- if (sd->rank == 1)
- vp_fat (1);
- else
- vp_fat (0);
-
- lseek (Ifile, sd->absaddr, L_SET);
- read (Ifile, &sb, sizeof sb);
- twiddle32 (&(sb.orgx));
- twiddle32 (&(sb.orgy));
- twiddle32 (&(sb.id));
- twiddle16 (&(sb.nstrokes));
-
- if (sd->nbytes > segbufsize)
- {
- fprintf (stderr, "Segment %d needs %d bytes; buffer limit is %d.\n", iseg, sd->nbytes, segbufsize);
- close (Ifile);
- free (sdbuf);
- free (segbuf);
- return;
- }
- read (Ifile, segbuf, sd->nbytes);
-
- k = 0;
-
- oln = sb.orgx;
- olt = sb.orgy;
-
- #ifdef DEBUG
- count = 1;
- deg = abs (oln) / 3600;
- min = (abs (oln) - deg * 3600) / 60;
- sec = abs (oln) - deg * 3600 - min * 60;
- if (oln > 0)
- fprintf (stderr, "+ %d %d %d %d\n", deg, min, sec, count);
- else
- fprintf (stderr, "- %d %d %d %d\n", deg, min, sec, count);
- #endif
-
- vp_penup ();
- project (CONV * olt / 3600., CONV * oln / 3600.);
-
- for (jstroke = 1; jstroke <= sb.nstrokes; jstroke++)
- {
- twiddle16 (&segbuf[k]);
- if (segbuf[k] & SHORTFLAG)
- {
- #ifdef DEBUG
- fprintf (stderr, "s ");
- #endif
- /* Flag bit on: unpack a 16-bit field into dx and dy */
- i32 = segbuf[k++];
- if (i32 > 0)
- i32 &= ~SHORTFLAG;
- idy = i32 & 0xFF;
- if (idy & 0x80)
- idy |= ~0xFF; /* extend sign */
- idx = i32 >> 8;
- if (idx & 0x80)
- idx |= ~0xBF; /* extend sign */
- }
- else
- {
- #ifdef DEBUG
- fprintf (stderr, "L ");
- #endif
- /* Flag bit off: take dx and dy from 32-bit fields. */
- idx = segbuf[k++];
- if (idx < 0)
- idx |= SHORTFLAG;
- twiddle16 (&segbuf[k]);
- idx = (idx << 16) | segbuf[k];
- k++;
-
- twiddle16 (&segbuf[k]);
- idy = segbuf[k];
- k++;
- if (idy < 0)
- idy |= SHORTFLAG;
- twiddle16 (&segbuf[k]);
- idy = (idy << 16) | segbuf[k];
- k++;
- }
- olt = olt + idy;
- oln = oln + idx;
-
- #ifdef DEBUG
- count++;
- deg = abs (oln) / 3600;
- min = (abs (oln) - deg * 3600) / 60;
- sec = abs (oln) - deg * 3600 - min * 60;
- if (oln > 0)
- fprintf (stderr, " + %d %d %d %d\n", deg, min, sec, count);
- else
- fprintf (stderr, " - %d %d %d %d\n", deg, min, sec, count);
- #endif
-
- project (CONV * olt / 3600., CONV * oln / 3600.);
- }
- }
- close (Ifile);
- free (sdbuf);
- free (segbuf);
- }
- }
-
- /*
- * Change the two routines below to accomodate the byte ordering on your
- * machine! - Joe Dellinger
- */
-
- twiddle32 (i32)
- BIT32 *i32;
- {
- BIT32 temp;
-
- temp = 0;
- temp |= 0xFF000000 & ((0x000000FF & *i32) << 24);
- temp |= 0x00FF0000 & ((0x0000FF00 & *i32) << 8);
- temp |= 0x0000FF00 & ((0x00FF0000 & *i32) >> 8);
- temp |= 0x000000FF & ((0xFF000000 & *i32) >> 24);
- *i32 = temp;
- }
-
- twiddle16 (i16)
- BIT16 *i16;
- {
- BIT16 temp;
-
- temp = 0;
- temp |= 0xFF00 & ((0x00FF & *i16) << 8);
- temp |= 0x00FF & ((0xFF00 & *i16) >> 8);
- *i16 = temp;
- }
-
-
- project (lati, longi)
- double lati, longi;
- {
- double xx, yy, zz;
- double x, y, z;
- double dot, factor;
-
- static double xlast = 0.;
-
- if (projection[0] == 'r')
- {
- x = sin (longi - viewlong) * cos (lati);
- y = cos (longi - viewlong) * cos (lati);
- z = sin (lati);
-
- yy = y * cos (viewlat) + z * sin (viewlat);
- zz = -y * sin (viewlat) + z * cos (viewlat);
- xx = x;
-
- dot = xx * xx + zz * zz - yy * (viewdist + (1. - yy));
-
- if (dot > 0.)
- {
- vp_penup ();
- return;
- }
-
- factor = viewdist / (viewdist + (1. - yy));
- xx *= factor;
- zz *= factor;
-
- vp_upendn (xx, zz);
- }
- else
- {
- x = longi - viewlong;
- while (x >= 180 * CONV)
- x -= 360 * CONV;
- while (x < -180 * CONV)
- x += 360 * CONV;
- y = lati;
-
- if (fabs (xlast - x) > 180. * CONV)
- vp_penup ();
- xlast = x;
-
- vp_upendn (x, y);
- }
- }
-
- double
- my_acos (x)
- double x;
- {
- if (fabs (x) >= 1.)
- return 0.;
- else
- return acos (x);
- }
-
- /*
- * Just eat any error message from getpar.
- */
- err ()
- {
- }
-